home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65 / src / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-05  |  14.0 KB  |  842 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)util.c    5.18 (Berkeley) 6/1/90";
  23. #endif /* not lint */
  24.  
  25. # include <stdio.h>
  26. # include <sys/types.h>
  27. # include <sys/stat.h>
  28. # include <sysexits.h>
  29. # include <errno.h>
  30. # include "sendmail.h"
  31.  
  32. /*
  33. **  STRIPQUOTES -- Strip quotes & quote bits from a string.
  34. **
  35. **    Runs through a string and strips off unquoted quote
  36. **    characters and quote bits.  This is done in place.
  37. **
  38. **    Parameters:
  39. **        s -- the string to strip.
  40. **        qf -- if set, remove actual `` " '' characters
  41. **            as well as the quote bits.
  42. **
  43. **    Returns:
  44. **        none.
  45. **
  46. **    Side Effects:
  47. **        none.
  48. **
  49. **    Called By:
  50. **        deliver
  51. */
  52.  
  53. stripquotes(s, qf)
  54.     char *s;
  55.     bool qf;
  56. {
  57.     register char *p;
  58.     register char *q;
  59.     register char c;
  60.  
  61.     if (s == NULL)
  62.         return;
  63.  
  64.     for (p = q = s; (c = *p++) != '\0'; )
  65.     {
  66.         if (c != '"' || !qf)
  67.             *q++ = c & 0177;
  68.     }
  69.     *q = '\0';
  70. }
  71. /*
  72. **  QSTRLEN -- give me the string length assuming 0200 bits add a char
  73. **
  74. **    Parameters:
  75. **        s -- the string to measure.
  76. **
  77. **    Reurns:
  78. **        The length of s, including space for backslash escapes.
  79. **
  80. **    Side Effects:
  81. **        none.
  82. */
  83.  
  84. qstrlen(s)
  85.     register char *s;
  86. {
  87.     register int l = 0;
  88.     register char c;
  89.  
  90.     while ((c = *s++) != '\0')
  91.     {
  92.         if (bitset(0200, c))
  93.             l++;
  94.         l++;
  95.     }
  96.     return (l);
  97. }
  98. /*
  99. **  CAPITALIZE -- return a copy of a string, properly capitalized.
  100. **
  101. **    Parameters:
  102. **        s -- the string to capitalize.
  103. **
  104. **    Returns:
  105. **        a pointer to a properly capitalized string.
  106. **
  107. **    Side Effects:
  108. **        none.
  109. */
  110.  
  111. char *
  112. capitalize(s)
  113.     register char *s;
  114. {
  115.     static char buf[50];
  116.     register char *p;
  117.  
  118.     p = buf;
  119.  
  120.     for (;;)
  121.     {
  122.         while (!isalpha(*s) && *s != '\0')
  123.             *p++ = *s++;
  124.         if (*s == '\0')
  125.             break;
  126.         *p++ = toupper(*s);
  127.         s++;
  128.         while (isalpha(*s))
  129.             *p++ = *s++;
  130.     }
  131.  
  132.     *p = '\0';
  133.     return (buf);
  134. }
  135. /*
  136. **  XALLOC -- Allocate memory and bitch wildly on failure.
  137. **
  138. **    THIS IS A CLUDGE.  This should be made to give a proper
  139. **    error -- but after all, what can we do?
  140. **
  141. **    Parameters:
  142. **        sz -- size of area to allocate.
  143. **
  144. **    Returns:
  145. **        pointer to data region.
  146. **
  147. **    Side Effects:
  148. **        Memory is allocated.
  149. */
  150.  
  151. char *
  152. xalloc(sz)
  153.     register int sz;
  154. {
  155.     register char *p;
  156.     extern char *malloc();
  157.  
  158.     p = malloc((unsigned) sz);
  159.     if (p == NULL)
  160.     {
  161.         syserr("Out of memory!!");
  162.         abort();
  163.         /* exit(EX_UNAVAILABLE); */
  164.     }
  165.     return (p);
  166. }
  167. /*
  168. **  COPYPLIST -- copy list of pointers.
  169. **
  170. **    This routine is the equivalent of newstr for lists of
  171. **    pointers.
  172. **
  173. **    Parameters:
  174. **        list -- list of pointers to copy.
  175. **            Must be NULL terminated.
  176. **        copycont -- if TRUE, copy the contents of the vector
  177. **            (which must be a string) also.
  178. **
  179. **    Returns:
  180. **        a copy of 'list'.
  181. **
  182. **    Side Effects:
  183. **        none.
  184. */
  185.  
  186. char **
  187. copyplist(list, copycont)
  188.     char **list;
  189.     bool copycont;
  190. {
  191.     register char **vp;
  192.     register char **newvp;
  193.  
  194.     for (vp = list; *vp != NULL; vp++)
  195.         continue;
  196.  
  197.     vp++;
  198.  
  199.     newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
  200.     bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);
  201.  
  202.     if (copycont)
  203.     {
  204.         for (vp = newvp; *vp != NULL; vp++)
  205.             *vp = newstr(*vp);
  206.     }
  207.  
  208.     return (newvp);
  209. }
  210. /*
  211. **  PRINTAV -- print argument vector.
  212. **
  213. **    Parameters:
  214. **        av -- argument vector.
  215. **
  216. **    Returns:
  217. **        none.
  218. **
  219. **    Side Effects:
  220. **        prints av.
  221. */
  222.  
  223. printav(av)
  224.     register char **av;
  225. {
  226.     while (*av != NULL)
  227.     {
  228.         if (tTd(0, 44))
  229.             printf("\n\t%08x=", *av);
  230.         else
  231.             (void) putchar(' ');
  232.         xputs(*av++);
  233.     }
  234.     (void) putchar('\n');
  235. }
  236. /*
  237. **  LOWER -- turn letter into lower case.
  238. **
  239. **    Parameters:
  240. **        c -- character to turn into lower case.
  241. **
  242. **    Returns:
  243. **        c, in lower case.
  244. **
  245. **    Side Effects:
  246. **        none.
  247. */
  248.  
  249. char
  250. lower(c)
  251.     register char c;
  252. {
  253.     return(isascii(c) && isupper(c) ? tolower(c) : c);
  254. }
  255. /*
  256. **  XPUTS -- put string doing control escapes.
  257. **
  258. **    Parameters:
  259. **        s -- string to put.
  260. **
  261. **    Returns:
  262. **        none.
  263. **
  264. **    Side Effects:
  265. **        output to stdout
  266. */
  267.  
  268. xputs(s)
  269.     register char *s;
  270. {
  271.     register char c;
  272.  
  273.     if (s == NULL)
  274.     {
  275.         printf("<null>");
  276.         return;
  277.     }
  278.     (void) putchar('"');
  279.     while ((c = *s++) != '\0')
  280.     {
  281.         if (!isascii(c))
  282.         {
  283.             (void) putchar('\\');
  284.             c &= 0177;
  285.         }
  286.         if (c < 040 || c >= 0177)
  287.         {
  288.             (void) putchar('^');
  289.             c ^= 0100;
  290.         }
  291.         (void) putchar(c);
  292.     }
  293.     (void) putchar('"');
  294.     (void) fflush(stdout);
  295. }
  296. /*
  297. **  MAKELOWER -- Translate a line into lower case
  298. **
  299. **    Parameters:
  300. **        p -- the string to translate.  If NULL, return is
  301. **            immediate.
  302. **
  303. **    Returns:
  304. **        none.
  305. **
  306. **    Side Effects:
  307. **        String pointed to by p is translated to lower case.
  308. **
  309. **    Called By:
  310. **        parse
  311. */
  312.  
  313. makelower(p)
  314.     register char *p;
  315. {
  316.     register char c;
  317.  
  318.     if (p == NULL)
  319.         return;
  320.     for (; (c = *p) != '\0'; p++)
  321.         if (isascii(c) && isupper(c))
  322.             *p = tolower(c);
  323. }
  324. /*
  325. **  BUILDFNAME -- build full name from gecos style entry.
  326. **
  327. **    This routine interprets the strange entry that would appear
  328. **    in the GECOS field of the password file.
  329. **
  330. **    Parameters:
  331. **        p -- name to build.
  332. **        login -- the login name of this user (for &).
  333. **        buf -- place to put the result.
  334. **
  335. **    Returns:
  336. **        none.
  337. **
  338. **    Side Effects:
  339. **        none.
  340. */
  341.  
  342. buildfname(p, login, buf)
  343.     register char *p;
  344.     char *login;
  345.     char *buf;
  346. {
  347.     register char *bp = buf;
  348.  
  349.     if (*p == '*')
  350.         p++;
  351.     while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
  352.     {
  353.         if (*p == '&')
  354.         {
  355.             (void) strcpy(bp, login);
  356.             *bp = toupper(*bp);
  357.             while (*bp != '\0')
  358.                 bp++;
  359.             p++;
  360.         }
  361.         else
  362.             *bp++ = *p++;
  363.     }
  364.     *bp = '\0';
  365. }
  366. /*
  367. **  SAFEFILE -- return true if a file exists and is safe for a user.
  368. **
  369. **    Parameters:
  370. **        fn -- filename to check.
  371. **        uid -- uid to compare against.
  372. **        mode -- mode bits that must match.
  373. **
  374. **    Returns:
  375. **        TRUE if fn exists, is owned by uid, and matches mode.
  376. **        FALSE otherwise.
  377. **
  378. **    Side Effects:
  379. **        none.
  380. */
  381.  
  382. bool
  383. safefile(fn, uid, mode)
  384.     char *fn;
  385.     int uid;
  386.     int mode;
  387. {
  388.     struct stat stbuf;
  389.  
  390.     if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
  391.         (stbuf.st_mode & mode) == mode)
  392.         return (TRUE);
  393.     errno = 0;
  394.     return (FALSE);
  395. }
  396. /*
  397. **  FIXCRLF -- fix <CR><LF> in line.
  398. **
  399. **    Looks for the <CR><LF> combination and turns it into the
  400. **    UNIX canonical <NL> character.  It only takes one line,
  401. **    i.e., it is assumed that the first <NL> found is the end
  402. **    of the line.
  403. **
  404. **    Parameters:
  405. **        line -- the line to fix.
  406. **        stripnl -- if true, strip the newline also.
  407. **
  408. **    Returns:
  409. **        none.
  410. **
  411. **    Side Effects:
  412. **        line is changed in place.
  413. */
  414.  
  415. fixcrlf(line, stripnl)
  416.     char *line;
  417.     bool stripnl;
  418. {
  419.     register char *p;
  420.  
  421.     p = index(line, '\n');
  422.     if (p == NULL)
  423.         return;
  424.     if (p > line && p[-1] == '\r')
  425.         p--;
  426.     if (!stripnl)
  427.         *p++ = '\n';
  428.     *p = '\0';
  429. }
  430. /*
  431. **  DFOPEN -- determined file open
  432. **
  433. **    This routine has the semantics of fopen, except that it will
  434. **    keep trying a few times to make this happen.  The idea is that
  435. **    on very loaded systems, we may run out of resources (inodes,
  436. **    whatever), so this tries to get around it.
  437. */
  438.  
  439. FILE *
  440. dfopen(filename, mode)
  441.     char *filename;
  442.     char *mode;
  443. {
  444.     register int tries;
  445.     register FILE *fp;
  446.  
  447.     for (tries = 0; tries < 10; tries++)
  448.     {
  449.         sleep((unsigned) (10 * tries));
  450.         errno = 0;
  451.         fp = fopen(filename, mode);
  452.         if (fp != NULL)
  453.             break;
  454.         if (errno != ENFILE && errno != EINTR)
  455.             break;
  456.     }
  457.     errno = 0;
  458.     return (fp);
  459. }
  460. /*
  461. **  PUTLINE -- put a line like fputs obeying SMTP conventions
  462. **
  463. **    This routine always guarantees outputing a newline (or CRLF,
  464. **    as appropriate) at the end of the string.
  465. **
  466. **    Parameters:
  467. **        l -- line to put.
  468. **        fp -- file to put it onto.
  469. **        m -- the mailer used to control output.
  470. **
  471. **    Returns:
  472. **        none
  473. **
  474. **    Side Effects:
  475. **        output of l to fp.
  476. */
  477.  
  478. # define SMTPLINELIM    990    /* maximum line length */
  479.  
  480. putline(l, fp, m)
  481.     register char *l;
  482.     FILE *fp;
  483.     MAILER *m;
  484. {
  485.     register char *p;
  486.     char svchar;
  487.  
  488.     /* strip out 0200 bits -- these can look like TELNET protocol */
  489.     if (bitnset(M_LIMITS, m->m_flags))
  490.     {
  491.         p = l;
  492.         while ((*p++ &= ~0200) != 0)
  493.             continue;
  494.     }
  495.  
  496.     do
  497.     {
  498.         /* find the end of the line */
  499.         p = index(l, '\n');
  500.         if (p == NULL)
  501.             p = &l[strlen(l)];
  502.  
  503.         /* check for line overflow */
  504.         while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags))
  505.         {
  506.             register char *q = &l[SMTPLINELIM - 1];
  507.  
  508.             svchar = *q;
  509.             *q = '\0';
  510.             if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
  511.                 (void) putc('.', fp);
  512.             fputs(l, fp);
  513.             (void) putc('!', fp);
  514.             fputs(m->m_eol, fp);
  515.             *q = svchar;
  516.             l = q;
  517.         }
  518.  
  519.         /* output last part */
  520.         svchar = *p;
  521.         *p = '\0';
  522.         if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
  523.             (void) putc('.', fp);
  524.         fputs(l, fp);
  525.         fputs(m->m_eol, fp);
  526.         *p = svchar;
  527.         l = p;
  528.         if (*l == '\n')
  529.             l++;
  530.     } while (l[0] != '\0');
  531. }
  532. /*
  533. **  XUNLINK -- unlink a file, doing logging as appropriate.
  534. **
  535. **    Parameters:
  536. **        f -- name of file to unlink.
  537. **
  538. **    Returns:
  539. **        none.
  540. **
  541. **    Side Effects:
  542. **        f is unlinked.
  543. */
  544.  
  545. xunlink(f)
  546.     char *f;
  547. {
  548.     register int i;
  549.  
  550. # ifdef LOG
  551.     if (LogLevel > 20)
  552.         syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
  553. # endif LOG
  554.  
  555.     i = unlink(f);
  556. # ifdef LOG
  557.     if (i < 0 && LogLevel > 21)
  558.         syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
  559. # endif LOG
  560. }
  561. /*
  562. **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
  563. **
  564. **    Parameters:
  565. **        buf -- place to put the input line.
  566. **        siz -- size of buf.
  567. **        fp -- file to read from.
  568. **
  569. **    Returns:
  570. **        NULL on error (including timeout).  This will also leave
  571. **            buf containing a null string.
  572. **        buf otherwise.
  573. **
  574. **    Side Effects:
  575. **        none.
  576. */
  577.  
  578. static jmp_buf    CtxReadTimeout;
  579.  
  580. char *
  581. sfgets(buf, siz, fp)
  582.     char *buf;
  583.     int siz;
  584.     FILE *fp;
  585. {
  586.     register EVENT *ev = NULL;
  587.     register char *p;
  588.     extern readtimeout();
  589.  
  590.     /* set the timeout */
  591.     if (ReadTimeout != 0)
  592.     {
  593.         if (setjmp(CtxReadTimeout) != 0)
  594.         {
  595. # ifdef LOG
  596.             syslog(LOG_NOTICE,
  597.                 "timeout waiting for input from %s\n",
  598.                 RealHostName? RealHostName: "local");
  599. # endif
  600.             errno = 0;
  601.             usrerr("451 timeout waiting for input");
  602.             buf[0] = '\0';
  603.             return (NULL);
  604.         }
  605.         ev = setevent((time_t) ReadTimeout, readtimeout, 0);
  606.     }
  607.  
  608.     /* try to read */
  609.     p = NULL;
  610.     while (p == NULL && !feof(fp) && !ferror(fp))
  611.     {
  612.         errno = 0;
  613.         p = fgets(buf, siz, fp);
  614.         if (errno == EINTR)
  615.             clearerr(fp);
  616.     }
  617.  
  618.     /* clear the event if it has not sprung */
  619.     clrevent(ev);
  620.  
  621.     /* clean up the books and exit */
  622.     LineNumber++;
  623.     if (p == NULL)
  624.     {
  625.         buf[0] = '\0';
  626.         return (NULL);
  627.     }
  628.     for (p = buf; *p != '\0'; p++)
  629.         *p &= ~0200;
  630.     return (buf);
  631. }
  632.  
  633. static
  634. readtimeout()
  635. {
  636.     longjmp(CtxReadTimeout, 1);
  637. }
  638. /*
  639. **  FGETFOLDED -- like fgets, but know about folded lines.
  640. **
  641. **    Parameters:
  642. **        buf -- place to put result.
  643. **        n -- bytes available.
  644. **        f -- file to read from.
  645. **
  646. **    Returns:
  647. **        buf on success, NULL on error or EOF.
  648. **
  649. **    Side Effects:
  650. **        buf gets lines from f, with continuation lines (lines
  651. **        with leading white space) appended.  CRLF's are mapped
  652. **        into single newlines.  Any trailing NL is stripped.
  653. */
  654.  
  655. char *
  656. fgetfolded(buf, n, f)
  657.     char *buf;
  658.     register int n;
  659.     FILE *f;
  660. {
  661.     register char *p = buf;
  662.     register int i;
  663.  
  664.     n--;
  665.     while ((i = getc(f)) != EOF)
  666.     {
  667.         if (i == '\r')
  668.         {
  669.             i = getc(f);
  670.             if (i != '\n')
  671.             {
  672.                 if (i != EOF)
  673.                     (void) ungetc(i, f);
  674.                 i = '\r';
  675.             }
  676.         }
  677.         if (--n > 0)
  678.             *p++ = i;
  679.         if (i == '\n')
  680.         {
  681.             LineNumber++;
  682.             i = getc(f);
  683.             if (i != EOF)
  684.                 (void) ungetc(i, f);
  685.             if (i != ' ' && i != '\t')
  686.             {
  687.                 *--p = '\0';
  688.                 return (buf);
  689.             }
  690.         }
  691.     }
  692.     return (NULL);
  693. }
  694. /*
  695. **  CURTIME -- return current time.
  696. **
  697. **    Parameters:
  698. **        none.
  699. **
  700. **    Returns:
  701. **        the current time.
  702. **
  703. **    Side Effects:
  704. **        none.
  705. */
  706.  
  707. time_t
  708. curtime()
  709. {
  710.     auto time_t t;
  711.  
  712.     (void) time(&t);
  713.     return (t);
  714. }
  715. /*
  716. **  ATOBOOL -- convert a string representation to boolean.
  717. **
  718. **    Defaults to "TRUE"
  719. **
  720. **    Parameters:
  721. **        s -- string to convert.  Takes "tTyY" as true,
  722. **            others as false.
  723. **
  724. **    Returns:
  725. **        A boolean representation of the string.
  726. **
  727. **    Side Effects:
  728. **        none.
  729. */
  730.  
  731. bool
  732. atobool(s)
  733.     register char *s;
  734. {
  735.     if (*s == '\0' || index("tTyY", *s) != NULL)
  736.         return (TRUE);
  737.     return (FALSE);
  738. }
  739. /*
  740. **  ATOOCT -- convert a string representation to octal.
  741. **
  742. **    Parameters:
  743. **        s -- string to convert.
  744. **
  745. **    Returns:
  746. **        An integer representing the string interpreted as an
  747. **        octal number.
  748. **
  749. **    Side Effects:
  750. **        none.
  751. */
  752.  
  753. atooct(s)
  754.     register char *s;
  755. {
  756.     register int i = 0;
  757.  
  758.     while (*s >= '0' && *s <= '7')
  759.         i = (i << 3) | (*s++ - '0');
  760.     return (i);
  761. }
  762. /*
  763. **  WAITFOR -- wait for a particular process id.
  764. **
  765. **    Parameters:
  766. **        pid -- process id to wait for.
  767. **
  768. **    Returns:
  769. **        status of pid.
  770. **        -1 if pid never shows up.
  771. **
  772. **    Side Effects:
  773. **        none.
  774. */
  775.  
  776. waitfor(pid)
  777.     int pid;
  778. {
  779.     auto int st;
  780.     int i;
  781.  
  782.     do
  783.     {
  784.         errno = 0;
  785.         i = wait(&st);
  786.     } while ((i >= 0 || errno == EINTR) && i != pid);
  787.     if (i < 0)
  788.         st = -1;
  789.     return (st);
  790. }
  791. /*
  792. **  BITINTERSECT -- tell if two bitmaps intersect
  793. **
  794. **    Parameters:
  795. **        a, b -- the bitmaps in question
  796. **
  797. **    Returns:
  798. **        TRUE if they have a non-null intersection
  799. **        FALSE otherwise
  800. **
  801. **    Side Effects:
  802. **        none.
  803. */
  804.  
  805. bool
  806. bitintersect(a, b)
  807.     BITMAP a;
  808.     BITMAP b;
  809. {
  810.     int i;
  811.  
  812.     for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
  813.         if ((a[i] & b[i]) != 0)
  814.             return (TRUE);
  815.     return (FALSE);
  816. }
  817. /*
  818. **  BITZEROP -- tell if a bitmap is all zero
  819. **
  820. **    Parameters:
  821. **        map -- the bit map to check
  822. **
  823. **    Returns:
  824. **        TRUE if map is all zero.
  825. **        FALSE if there are any bits set in map.
  826. **
  827. **    Side Effects:
  828. **        none.
  829. */
  830.  
  831. bool
  832. bitzerop(map)
  833.     BITMAP map;
  834. {
  835.     int i;
  836.  
  837.     for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
  838.         if (map[i] != 0)
  839.             return (FALSE);
  840.     return (TRUE);
  841. }
  842.